home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-05-10 | 11.1 KB | 481 lines | [TEXT/MMCC] |
- //==================================================================
- // DirScrnWrite.c <tur xx-xx-92>
- //
- // Direct Screen Write Routines, hacked from my other bitz...
- //
- // Comments, Bug Reports/Fixes, etc, to turly@isltd.insignia.com
- //
- //==================================================================
-
- #ifndef __QUICKDRAW__
- #include "LoadMacHeaders.h"
- #endif /* __QUICKDRAW__ */
-
- #include "RectUtils.h"
- #include "DirScrnWrite.h"
- #include "Failure.h"
-
-
- //
-
- /* Want to find out if a GDevice is actually being used? Use this: */
-
- #define kScrnDevMask ((1 << screenDevice) | (1 << screenActive))
- #define IsActiveScreen(gdh) (((*gdh)->gdFlags & kScrnDevMask) == kScrnDevMask)
-
- #define kRGBTOLERANCE 0x2000
-
-
- // Nasty lowmem globals...
-
- #define GetDeviceList() (*(GDHandle *)0x08A8)
- #define GetCrsrVis() (*(char *)0x08CC)
- #define GetMMU32Bit() (*(char *)0x0CB2)
- #ifndef GetMBarHeight
- #define GetMBarHeight() (*(short*)0x0BAA)
- #endif
- #define GetMainDevice() (*(GDHandle *)0x08A4)
-
-
- /***********************************************************************************/
-
- long *ReplicatedByteLUT;
- int gPaletteColorsUsed;
- CTabHandle gDirClut;
- PaletteHandle gDirPalette;
- GDHandle gTheScreenDevice;
-
- const Point nullPt = {0, 0};
-
-
- /**/
-
-
- static Rect *cursorShieldRect;
- static char gOriginally32Bit, gPreviouslyVisible;
- static Rect gGlobalWinRect;
- static unsigned long gMacRowBytes;
- static unsigned long gMacScreenPtr, gWinScreenPtr;
- static RgnHandle gPreviousVisRgn, gBoundRgn;
- static int gDirScrnInited = 0,
- gDirScrnWindowInited = 0;
-
- /**/
-
-
- /* BeginDirectScreenWrite
- ** The rectangle into which you're writing, if passed, should be in GLOBAL COORDINATES.
- ** We may need to get the system into 32-bit mode when writing to the screen...
- */
- void BeginDirectScreenWrite(Rect *globalRect)
- {
- if ((cursorShieldRect = globalRect) != nil)
- ShieldCursor(globalRect, nullPt);
-
- gOriginally32Bit = GetMMU32Bit();
-
- if (gOriginally32Bit == false32b) {
- char b32 = true32b;
-
- SwapMMUMode(&b32);
- }
- }
-
-
- /**/
-
-
- void EndDirectScreenWrite(void)
- {
- if (!gOriginally32Bit) {
- char b24 = false32b;
-
- SwapMMUMode(&b24);
- }
-
- if (cursorShieldRect)
- ShowCursor();
- }
-
-
- /**/
-
-
- // If wp is completely visible, returns its business Rect in "gGlobalWinRect."
-
- static Boolean GetVisibleRect(WindowPtr wp) // return true if completely visible
- {
- Rect *boundP;
- Rect locRect, globRect;
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(wp);
-
- locRect = wp->portRect;
-
- // get the window’s rect in global coords
- globRect = locRect;
-
- LocalToGlobal((Point *)&globRect);
- LocalToGlobal(&((Point *)&globRect)[1]);
-
- // The visrgns could be the same if the window was moved onscreen but is still
- // "equally" visible after the move... (Recall: visRgns are in LOCAL coords!)
-
- if (!EqualRect(&globRect, &gGlobalWinRect) || !EqualRgn(gPreviousVisRgn, wp->visRgn)) {
-
- CopyRgn(wp->visRgn, gPreviousVisRgn); // Copy it...
-
- gPreviouslyVisible = false; // Assume that the window is obscured until proven otherwise
-
- gGlobalWinRect = globRect; // copy rectangles
-
- RectRgn(gBoundRgn, &locRect); // "locRect" -- local coords
- SectRgn(gBoundRgn, gPreviousVisRgn, gBoundRgn);
-
- // The result of this intersection must be a rectangle with no holes;
- // i.e., the window must be completely visible.
-
- if ((*gBoundRgn)->rgnSize == 10) { // size of a "pure" rectangular region
- boundP = &(*wp->visRgn)->rgnBBox;
-
- if (RectInRect(&locRect, boundP)) { // locRect completely inside the bounds rect
- gPreviouslyVisible = true;
- }
- }
- }
-
- SetPort(oldPort);
-
- return gPreviouslyVisible;
- }
-
-
- /**/
-
- // CanWriteDirectToScreen -- return true if we can write directly onscreen to the entire "win".
-
- Boolean CanWriteDirectToScreen(WindowPtr win)
- {
- GDHandle gdh;
- Rect *gdRP;
-
- FailNil(win);
-
- if (GetVisibleRect(win)) { // Window must be completely visible
-
- // Search thru all devices for this Rect
-
- gdh = GetDeviceList();
- while (gdh != 0) {
- gdRP = &(*gdh)->gdRect;
- if (RectInRect(&gGlobalWinRect, gdRP)) {
-
- // We may be able to write directly to the screen...
-
- if (IsActiveScreen(gdh)) {
- PixMapHandle pmh;
-
- pmh = (*gdh)->gdPMap;
- if ((*pmh)->pixelType == clutType && (*pmh)->pixelSize == 8) {
- gMacRowBytes = (*pmh)->rowBytes & 0x3fff;
- gMacScreenPtr = (unsigned long)(*pmh)->baseAddr;
- gWinScreenPtr = gMacScreenPtr +
- ((gGlobalWinRect.top - gdRP->top) * gMacRowBytes) + gGlobalWinRect.left - gdRP->left;
- gTheScreenDevice = gdh;
- return true;
- }
- }
- }
- gdh = (GDHandle)(*gdh)->gdNextGD;
- }
- }
-
- return false;
- }
-
-
- /**/
-
-
- Boolean CheckDirScrnWriteFor(WindowPtr win)
- {
- return CanWriteDirectToScreen(win);
- }
-
-
- void NotMungeFunc(unsigned char *screenPtr, unsigned char *srcPtr)
- {
- *screenPtr = ~*srcPtr;
- }
-
-
- /**/
-
-
- // Copy 8-bit pixels from "src" to the current port, no colour mapping....
- // CanWriteDirectToScreen() is assumed to have returned TRUE...
- void DirCopyPix(register long *srcPixels,
- unsigned long srcRB,
- int srcWid,
- register int srcHt,
- int winStartX, int winStartY, // top/left of rect in window
- PixMungeFunc mungeFunc)
- {
- Rect dst;
- unsigned long dstRB;
- register int wid = srcWid;
- register long *macPtr = (long *)(gWinScreenPtr + (gMacRowBytes*winStartY) + winStartX);
-
- FailIf(wid & 0xF); // || srcHt & 0x3)
-
- dst = gGlobalWinRect;
- dst.top = gGlobalWinRect.top + winStartY;
- dst.bottom = dst.top + srcHt;
- dst.left = gGlobalWinRect.left + winStartX;
- dst.right = dst.left + srcWid;
- BeginDirectScreenWrite(&dst);
-
- srcRB /= sizeof(*srcPixels); // we move longwords, so convert byte count to long count
- wid /= sizeof(*srcPixels); // ditto
-
- // pre-adjust the rowBytes values
- dstRB = (gMacRowBytes / sizeof(*srcPixels)) - wid;
- srcRB -= wid;
-
-
- if (mungeFunc) {
- srcWid = wid; // keep tabs on this!
- do {
- wid = srcWid;
- do {
- mungeFunc((unsigned char *)macPtr, (unsigned char *)srcPixels);
- mungeFunc(((unsigned char *)macPtr)+1, ((unsigned char *)srcPixels)+1);
- mungeFunc(((unsigned char *)macPtr)+2, ((unsigned char *)srcPixels)+2);
- mungeFunc(((unsigned char *)macPtr)+3, ((unsigned char *)srcPixels)+3);
- ++macPtr;
- ++srcPixels;
- } while (--wid);
- srcPixels += srcRB;
- macPtr += dstRB;
- } while (--srcHt);
- }
- else { // just a plain copy!
- srcWid = wid >> 2; // we move 4 longs per iteration
- do {
- wid = srcWid;
- do {
- *macPtr++ = *srcPixels++;
- *macPtr++ = *srcPixels++;
- *macPtr++ = *srcPixels++;
- *macPtr++ = *srcPixels++;
- } while (--wid);
- srcPixels += srcRB;
- macPtr += dstRB;
- } while (--srcHt);
- }
-
- EndDirectScreenWrite();
- }
-
-
- /**/
-
- // Copy 8-bit pixels from "src" to the current port, no colour mapping....
- // CanWriteDirectToScreen() is assumed to have returned TRUE...
- // We scale every source pixel by 2 destination ones (handy for PC VGA
- // 320x200 => Mac 640x400...)
-
- void DirCopyPixScaled2(long *paramSrcPixels,
- unsigned long srcRB,
- int srcWid,
- register int srcHt,
- int winStartX, int winStartY, // top/left of rect in window
- PixMungeFunc mungeFunc)
- {
- Rect dst;
- register unsigned short *macPtr;
- register unsigned char *srcPixels = (unsigned char *)paramSrcPixels;
- unsigned long dstRB;
- register int nextLine,
- wid = srcWid;
-
- FailIf(wid & 0xF); // || srcHt & 0x3)
-
- macPtr = (unsigned short *)(gWinScreenPtr + (gMacRowBytes * winStartY) + winStartX);
-
- dst = gGlobalWinRect;
- dst.top = gGlobalWinRect.top + winStartY;
- dst.bottom = dst.top + (srcHt << 1);
- dst.left = gGlobalWinRect.left + winStartX;
- dst.right = dst.left + (srcWid << 1);
- BeginDirectScreenWrite(&dst);
-
- // pre-adjust the rowBytes values
-
- dstRB = (gMacRowBytes * 2 / sizeof(*macPtr)) - wid; // we do 2 lines at a time
- srcRB -= wid;
-
- // Arrange "nextLine" so that "macPtr[nextLine]" is the pixel immediately below "macPtr"
-
- nextLine = gMacRowBytes / sizeof(*macPtr);
-
- if (mungeFunc) {
- srcWid = wid; // keep tabs on this!
- do {
- wid = srcWid;
- do {
- mungeFunc((unsigned char *)macPtr, srcPixels);
- macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*(unsigned char *)macPtr];
- ++macPtr;
- ++srcPixels;
- } while (--wid);
- srcPixels += srcRB;
- macPtr += dstRB;
- } while (--srcHt);
- }
- else { // just a plain copy!
- srcWid = wid >> 2; // we do 4 pixels per loop iteration...
- do {
- wid = srcWid;
- do {
- macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
- ++macPtr;
- ++srcPixels;
- macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
- ++macPtr;
- ++srcPixels;
- macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
- ++macPtr;
- ++srcPixels;
- macPtr[0] = macPtr[nextLine] = ReplicatedByteLUT[*srcPixels];
- ++macPtr;
- ++srcPixels;
- } while (--wid);
- srcPixels += srcRB;
- macPtr += dstRB;
- } while (--srcHt);
- }
-
- EndDirectScreenWrite();
- }
-
-
- /**/
-
-
- void InitDirScrnGraphicsWindow(WindowPtr wp, InitPaletteFunc ipf)
- {
- int i, numColors = 256;
- GDHandle oldDev;
- GrafPtr rememberedPort;
-
- FailIfNot(gDirScrnInited); // system must be initialised
- FailIf(gDirScrnWindowInited); // the particular window MUST NOT BE INITIALISED!
- FailNil(wp); // window and initpal func cannot be nil
- FailNil(ipf);
-
- gDirScrnWindowInited = true;
-
- // Remember the previous port & device...
-
- GetPort(&rememberedPort);
- oldDev = GetGDevice();
-
- SetPort(wp);
-
- gDirClut = nil;
-
- // NB: •MUST• Have Explicit + Animated here...
-
- gDirPalette = NewPalette(numColors, nil, pmAnimated + pmExplicit + pmTolerant, kRGBTOLERANCE);
- gDirClut = (CTabHandle)NewHandleClear(sizeof(ColorTable) - sizeof(ColorSpec));
-
- if (gDirClut && gDirPalette) {
-
- gPaletteColorsUsed = ipf(gDirPalette);
- FailIf(gPaletteColorsUsed <= 0);
-
- Palette2CTab(gDirPalette, gDirClut);
-
- // Make sure each value field of the colortable is assigned to the
- // corresponding entry in the palette and make sure the ctSeed field
- // is given a unique value.
-
- for (i = 0; i < numColors; ++i)
- (*gDirClut)->ctTable[i].value = i;
-
- i = GetCTSeed();
- (*gDirClut)->ctSeed = i;
-
- // Setting bit 14 of the “ctFlags” field tells the color table to refer
- // to the palette indexes instead of its rgb values. This is necessary
- // since we (might) perform animation by altering the palette.
-
- (*gDirClut)->ctFlags |= (0x8000|0x4000);
-
- // Associate the new palette with our window.
-
- SetPalette(wp, gDirPalette, /*pmUpdates:*/ true);
-
- AnimatePalette(wp, gDirClut, 0, 0, (*gDirClut)->ctSize+1);
- }
-
- // Restore the original port.
-
- SetGDevice(oldDev);
- SetPort(rememberedPort);
- }
-
-
- /**/
-
-
- void TermDirScrnGraphicsWindow(WindowPtr wp)
- {
- FailIfNot(gDirScrnInited);
- FailIfNot(gDirScrnWindowInited);
- FailNil(gDirClut);
- FailNil(gDirPalette);
-
- DisposeCTable(gDirClut);
- gDirClut = 0;
-
- DisposePalette(gDirPalette);
- gDirPalette = 0;
-
- gDirScrnWindowInited = false;
- }
-
-
- /**/
-
-
- void InitDirScrnWrite(void) // initialise the system
- {
- int i, j;
-
- FailIf(gDirScrnInited); // cannot already be initialised
-
- // Create a couple of empty regions...
-
- gPreviousVisRgn = NewRgn();
- gBoundRgn = NewRgn();
-
- // Fixup the replicated byte ==> longword lut...
-
- ReplicatedByteLUT = (long *)NewPtr(256 * sizeof(long));
- FailNil(ReplicatedByteLUT);
-
- for (i = 0; i < 256; ++i) {
- char *p = (char *)(ReplicatedByteLUT + i);
- for (j = 0; j < sizeof(long); ++j)
- p[j] = i;
- }
-
- gDirScrnInited = true;
- }
-
-
-